home *** CD-ROM | disk | FTP | other *** search
/ CD ROM Paradise Collection 4 / CD ROM Paradise Collection 4 1995 Nov.iso / system / p87test.zip / P87TEST.ASM next >
Assembly Source File  |  1994-11-14  |  10KB  |  343 lines

  1.         .model tiny
  2.  
  3.         .data
  4. bugnr   dt      824633702449.0
  5. diff    dt      ?
  6.  
  7. feature_bits dd ?
  8.  
  9. cpu_msg dw      I808x$, I186$, I286$, I386$, I486$, cpuid5$
  10. ndp_msg dw      No87$, I8087$, I287$, I387$
  11.  
  12. feature_list dw fpu$, vme$, iobrk$, pse$, tsc$, p5msr$, 0, mce$, cx8$
  13.  
  14. cprt    db      'Pentium FDIV bug finder. V1.1 (c) Terje Mathisen 1994'
  15.         db      13,10,13,10,'$'
  16.  
  17. I808x$  db      'This is an 808x cpu',13,10,'$'
  18. I186$   db      'This is a 186 cpu',13,10,'$'
  19. I286$   db      'This is a 286 cpu',13,10,'$'
  20. I386$   db      'This is a 386 cpu',13,10,'$'
  21. I486$   db      'This is a 486 cpu',13,10,'$'
  22. cpuid5$ db      'This is a Pentium or better cpu',13,10,'$'
  23.  
  24. No87$   db      'It has no ndp!',13,10,'$'
  25. I8087$  db      'It has an 8087 ndp',13,10,'$'
  26. I287$   db      'It has a 287 ndp',13,10,'$'
  27. I387$   db      'It has a 387 or later ndp',13,10,'$'
  28.  
  29. feature_msg1$ db 13,10,'CPU feature list:',13,10
  30.  
  31. fpu$    db      '  1 : FPU (NDP) onchip',13,10,'$'
  32. vme$    db      '  2 : Virtual 86 Mode Extensions',13,10,'$'
  33. iobrk$  db      '  4 : I/O Breakpoints',13,10,'$'
  34. pse$    db      '  8 : Page Size Extensions',13,10,'$'
  35. tsc$    db      ' 10 : Time Stamp Counter',13,10,'$'
  36. p5msr$  db      ' 20 : Pentium style Model Specific Registers',13,10,'$'
  37. mce$    db      ' 80 : Machine Check Exception',13,10,'$'
  38. cx8$    db      '100 : CMPXCHG8B instruction available',13,10,13,10,'$'
  39.  
  40. feature_msg2$ db '$'
  41.  
  42. earlyP5$ db 'This is an early Pentium, with only partial CPUID support!',13,10,'$'
  43.  
  44. cpuid_result$   db 13,10,'CPUID reports back:',13,10
  45.         db      'Vendor id = "'
  46. vendor_id dd    3 dup (?)
  47.         db      '"',13,10
  48.         db      'Family (4=486, 5=Pentium etc.) = '
  49. make$   dw      '00'
  50.         db      ', stepping = '
  51. step$   dw      '00'
  52.         db      ', model = '
  53. model$  dw      '00'
  54.         db      13,10,'$'
  55.  
  56. FPU_bug$ db     13,10,'It has the FDIV bug:',13,10
  57.    db  '(1.0/824633702449.0)*824633702449.0 is not equal to 1.0!',13,10,'$'
  58.  
  59. FPU_OK$ db      13,10,'It does not have the FDIV bug!',13,10,'$'
  60.  
  61. stepping db     ?
  62. CPUModel db     ?
  63. Cpu_Type db     ?       ; 0,1,2,3,4,5 etc
  64. Ndp_Type db     ?       ; None, 8087, 287, 387+
  65. have_cpuid db   0
  66.  
  67. Notp5$  db      'The FDIV bug occurs only on Pentium cpus!',13,10,'$'
  68.  
  69.         .code
  70.         org     100h
  71. start   proc    far
  72.  
  73.         lea     dx,[cprt]
  74.         mov     ah,9
  75.         int     21h
  76.  
  77.         call    getcpu
  78.  
  79.         mov     bl,[cpu_type]
  80.         cmp     bl,5
  81.          jbe    @@ok
  82.         mov     bl,5
  83. @@ok:
  84.         xor     bh,bh
  85.         add     bx,bx
  86.         mov     dx,cpu_msg[bx]
  87.         mov     ah,9
  88.         int     21h
  89.  
  90.         test    [have_cpuid],-1
  91.          jz     no_cpuid
  92.  
  93.         mov     bx, word ptr [feature_bits]
  94.         mov     ax, word ptr [feature_bits+2]
  95.         or      ax,bx
  96.         lea     dx,[earlyP5$]
  97.          jz     dispMsg
  98.  
  99. ;
  100. ; We have full CPUID support on this cpu, report back what we found!
  101. ;
  102.         mov     al,[stepping]
  103.         xor     ah,ah
  104.         mov     bl,10
  105.         div     bl
  106.         add     ax,'00'
  107.         mov     [step$],ax
  108.  
  109.         mov     al,[CpuModel]
  110.         xor     ah,ah
  111.         div     bl
  112.         add     ax,'00'
  113.         mov     [model$],ax
  114.  
  115.         mov     al,[cpu_type]
  116.         xor     ah,ah
  117.         div     bl
  118.         add     ax,'00'
  119.         mov     [make$],ax
  120.         
  121.         lea     dx,[cpuid_result$]
  122.         mov     ah,9
  123.         int     21h
  124. ;
  125. ; Display feature bits definitions:
  126. ;
  127.         lea     dx,[feature_msg1$]
  128.         mov     ah,9
  129.         int     21h
  130.  
  131.         lea     si,[feature_list-2]
  132.         mov     cx,9            ; Nr of currently defined feature bits
  133.         mov     di,word ptr [feature_bits]
  134.  
  135. @@next_feature:
  136.         add     si,2
  137.         shr     di,1
  138.          jnc    @@skip_feature
  139.         mov     dx,[si]
  140.         mov     ah,9
  141.         int     21h
  142.  
  143. @@skip_feature:
  144.         dec     cx
  145.          jnz    @@next_feature
  146.  
  147.         lea     dx,[feature_msg2$]
  148. dispMsg:
  149.         mov     ah,9
  150.         int     21h
  151.  
  152. no_cpuid:
  153.         call    getndp
  154.         mov     bl,[ndp_type]
  155.         cmp     bl,3
  156.          jbe    @@ndp_ok
  157.         mov     bl,3
  158. @@ndp_ok:
  159.         xor     bh,bh
  160.         add     bx,bx
  161.         mov     dx,ndp_msg[bx]
  162.         mov     ah,9
  163.         int     21h
  164.  
  165.         test    bx,bx
  166.          jz     exit            ; No NDP, so no NDP bug either! :-)
  167.  
  168.         call    testndp
  169.         lea     dx,[FPU_OK$]
  170.          jz     @@disp_bug
  171.         lea     dx,[FPU_Bug$]
  172. @@disp_bug:
  173.         mov     ah,9
  174.         int     21h
  175.  
  176. exit:
  177.         mov     ax,4c00h
  178.         int     21h             ; All done!
  179. start   endp
  180.  
  181. getcpu  proc    ; return 0,1,2,3,4,5 etc in BL for 808x,186,286,386...
  182.  
  183.         pushf
  184.         pop     ax
  185.         and     ah,0fh          ; Try to clear four upper flag bits!
  186.         push    ax
  187.         popf
  188.         pushf
  189.         pop     ax
  190.         xor     bx,bx           ; Assume 808x -> BX = 0
  191.         cmp     ah,0f0h
  192.          jae    getcpu_done     ; All four upper bits set -> 808x!
  193.  
  194.         or      ah,0f0h         ; Try to set the upper four bits:
  195.         push    ax
  196.         popf
  197.         pushf
  198.         pop     ax
  199.         and     ah,0f0h         ; Isolate them
  200.         mov     bx,2            ; This is a 286!
  201.          jz     getcpu_done     ; Just a 286, no FDIV problem!
  202. ;
  203. ; *************** 386+ code *******************
  204. ;
  205.         inc     bx              ; BX = 3, for 386+ cpus
  206.  
  207.         .486
  208.         mov     edx,esp
  209.         and     esp,not 3               ; DWORD-align the stack to allow AC!
  210.  
  211.         pushfd
  212.         pop     eax
  213.         mov     ecx,eax
  214.         xor     eax,1 SHL 18    ; AC flag == bit # 18!
  215.         push    eax
  216.         popfd
  217.         pushfd
  218.         pop     eax
  219.         push    ecx
  220.         popfd                   ; Restore original eflags
  221.         mov     esp,edx         ; Restore word-aligned stack ptr
  222.  
  223.         xor     eax,ecx         ; Could we toggle the AC flag?
  224.          jz     getcpu_done     ; No, so this is a 386!
  225.  
  226.         inc     bx              ; BX = 4(86)
  227.         mov     eax,ecx
  228.         xor     eax,1 SHL 21    ; ID flag == bit # 21!
  229.         push    eax
  230.         popfd
  231.         pushfd
  232.         pop     eax
  233.         push    ecx
  234.         popfd
  235.         xor     eax,ecx         ; Could we toggle the ID bit?
  236.          jnz    haveCPUID       ; Yes, so use CPUID to get more info!
  237.  
  238.                                 ; Drop through to exit for 486 case
  239. getcpu_done:
  240.         mov     [cpu_type],bl
  241.         ret                     ; Return with BX = CPU ID
  242.  
  243. haveCPUID:
  244.         mov     [have_cpuid],1  ; At least some support for CPUID
  245.  
  246. ; Use CPUID instruction to get more info!
  247.         xor     eax,eax         ; EAX == 0 -> Basic CPUID report
  248.         db      0Fh, 0A2h       ; CPUID opcode!
  249.  
  250.         mov     [vendor_id],ebx
  251.         mov     [vendor_id+4],edx
  252.         mov     [vendor_id+8],ecx
  253.         test    eax,eax         ; Are other values in EAX valid?
  254.          jz     getcpu_done     ; No, so this is an early Pentium!
  255.  
  256.         mov     eax,1
  257.         db      0Fh, 0A2h       ; CPUID opcode!
  258.         mov     [feature_bits],edx
  259.         and     ah,15           ; CPU Family [4(486), 5 (Pentium) etc]
  260.         mov     [cpu_type],ah   ; Save it! (Return value)
  261.         mov     bl,ah
  262.         xor     bh,bh
  263.  
  264.         mov     ah,al
  265.         shr     ah,4
  266.         and     al,15
  267.         mov     [stepping],al
  268.         mov     [CpuModel],ah
  269.         .8086
  270.  
  271.         ret
  272. getcpu  endp
  273.  
  274.         .data
  275. cw      dw      ?
  276.  
  277.         .code
  278.  
  279. getndp  proc
  280.         fninit
  281.         xor     dx,dx                   ; DL = (NO87, 8087, 287, 387+)
  282.         mov     bx,offset cw
  283.         mov     [bx],dx                 ; Make sure ControlWord is zero!
  284.         fnstcw  [bx]
  285.          jmp    $+2                     ; Wait for result
  286.          jmp    $+2                     ; Wait for result
  287.          jmp    $+2                     ; Wait for result
  288.         cmp     byte ptr [bx+1],03
  289.          jne    ndpdone                 ; NO 87 installed!
  290.  
  291.         fdisi                           ; Try to Disable x87 interrupts
  292.         fstcw   [bx]
  293.         inc     dx                      ; At least 8087
  294.         fwait                           ; Wait for result from FSTCW
  295.         test    byte ptr [bx],80h       ; DISI bit set?
  296.          jnz    ndpdone                 ; Yes, it's a 8087
  297.  
  298.         .286
  299.         .287
  300.         inc    dx                       ; 80287 or 80387
  301.         fld1                            ; 1.0
  302.         fldz                            ; 0.0
  303.         fdivp   st(1),st                ; 1.0 / 0.0 = +Inf
  304.         fld     st(0)                   ; Duplicate
  305.         fchs                            ; = -Inf
  306.         fcompp                          ; Are +Inf equal to -Inf?
  307.         fwait                           ; Wait for result
  308.         fstsw   ax
  309.         sahf                            ; Status from float point cmp
  310.          je     ndpdone                 ; +Inf == -Inf => 287
  311.         inc     dx                      ; 387
  312.         .8086
  313.         .8087
  314. ndpdone:
  315.         mov    [ndp_type],dl
  316.         ret
  317.  
  318. getndp  endp
  319.  
  320. testndp proc
  321. ; Check for FPU bug: Return Z(ero)/NonZero for OK/Bad
  322.  
  323.         finit
  324.         fld1
  325.         fld     [bugnr]
  326.         fdivp   st(1),st
  327.         fld     [bugnr]
  328.         fmulp   st(1),st
  329.         fld1
  330.         fsubp   st(1),st
  331.         fstp    [diff]
  332.         fwait
  333.         mov     ax,word ptr [diff+6]
  334.         and     ah,3fh                   ; Throw away two MS bits
  335.         or      ax,word ptr [diff]
  336.         or      ax,word ptr [diff+2]
  337.         or      ax,word ptr [diff+4]
  338.         ret
  339. testndp endp
  340.  
  341.         end     start
  342.  
  343.